package com.gosling.gosling.sooyoo;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.gosling.cloudspace.common.origincode.hashmap.HashMapTa;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * MapTest test
 */
public class SooYooLoanPlanTest {

    /***
     * hashCode值进行计算
     * @param value
     * @return
     */
    public static int hashCode(byte[] value) {
        int h = 0;
        for (byte v : value) {
            h = 31 * h + (v & 0xff);
        }
        return h;
    }

    /***
     * map拿到hashCode值后再计算得到新值
     * 减少hash碰撞
     * @param key
     * @return
     */
    static final int hash(Object key) {
        int h;
        if ((key == null)) {
            return 0;
        } else {
            h = key.hashCode();
            //无符号右移
            //能使高16位的特征与低16位的特征进行混合，得到新的数值
            int right = h >>> 16;
            //进行异或操作，X⊕0=X X⊕X=0
            return h ^ right;
        }
    }

    private static int concurrntHash(Object k) {


        int h = 0;
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();

        h ^= k.hashCode();
        System.out.println(h);

        h += (h << 15) ^ 0xffffcd7d;
        System.out.println("0xffffcd7d：" + 0xffffcd7d);
        System.out.println(h);
        h ^= (h >>> 10);
        System.out.println(h);
        h += (h << 3);
        System.out.println(h);
        h ^= (h >>> 6);
        System.out.println(h);
        h += (h << 2) + (h << 14);
        System.out.println(h);
        h = h ^ (h >>> 16);
        return h;
    }


    public static void main(String[] args) throws Exception {

        test0009();

    }

    private static void test0009() {
        HashMapTa<Object, Object> mapTa = new HashMapTa<>(2);
        mapTa.put("AaAaAaAaAa", "元素序号1");
        mapTa.put("AaAaAaAaBB", "元素序号2");
        mapTa.put("AaAaAaBBAa", "元素序号3");
        mapTa.put("AaAaAaBBBB", "元素序号4");
        mapTa.put("AaAaBBAaAa", "元素序号5");
        mapTa.put("AaAaBBAaBB", "元素序号6");
        mapTa.put("AaAaBBBBAa", "元素序号7");
        mapTa.put("AaAaBBBBBB", "元素序号8");
        mapTa.put("AaBBAaAaAa", "元素序号9");
        mapTa.put("AaBBAaAaBB", "元素序号10");
        mapTa.put("AaBBAaBBAa", "元素序号11");

//
//        BigDecimal financingYearRate = new BigDecimal("1").subtract(new BigDecimal("2"));
//        BigDecimal abs = financingYearRate.max(BigDecimal.ZERO);
//
//        System.out.println(abs);
//        String x = null;
//        String a = String.valueOf(x);
//        String b = "412";
//        System.out.println(ObjectUtil.equal(String.valueOf(a), b));
//        System.out.println(IdUtil.getSnowflake().nextIdStr());
//
//        LocalDateTime nowtime = LocalDateTime.now();
//        LocalDate now = LocalDate.now();
//        LocalDate now1 = LocalDate.of(2023,11,13);
//        LocalDate now2 = LocalDate.of(2024,1,15);
//        now.plusMonths(1);
//        System.out.println(nowtime);
//        System.out.println(Math.abs(ChronoUnit.DAYS.between(now1, now2)));
////        System.out.println(a.equals(b));
//
//
//        List<String> list = new ArrayList<>();
//        list.add("1");
//        list.add("2");
//        list.add("3");
//        List<String> collect = list.stream().filter(ab -> "1".equals(ab)).collect(Collectors.toList());
//        System.out.println(collect);
//
//        for (int i = 0; i < 5; i++) {
//            System.out.println(RandomUtil.randomInt(2));
//
//        }

//        Assert.isTrue(IdcardUtil.isValidCard("420101199504288708"), CommonException.tryError("身份证格式校验错误"));

//        System.out.println(getNexMonDate(LocalDate.now(), 5, 15, "FIXED"));
//        System.out.println(LocalDateTime.now().plusHours(-24).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

//        //应还款时间
//        LocalDate payableDate = LocalDate.of(2023, 11, 12);
//        //逾期天数
//        Long overdueDays = Math.abs(ChronoUnit.DAYS.between(LocalDate.now(), payableDate));
//        //罚息主体为---剩余本金
//        BigDecimal surplusPrincipalAmt = new BigDecimal("1700");
//        //罚息主体---剩余本金：逾期天数 * 剩余本金 * 罚息率 = 罚息，挂在第一个逾期的月份上
//        BigDecimal punishRate = new BigDecimal("0.1").divide(new BigDecimal("360"),6, RoundingMode.HALF_DOWN).multiply(new BigDecimal(overdueDays)).multiply(surplusPrincipalAmt);
//
//        System.out.println(punishRate);

//        Boolean flag = true;
//        String createTime = "2023-12-13 10:11:14";
//        if (StrUtil.isNotBlank(createTime)) {
//            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//            LocalDateTime orderDateTime = LocalDateTime.parse(createTime, dateTimeFormatter);
//            long until = orderDateTime.until(LocalDateTime.now(), ChronoUnit.HOURS);
//            boolean b = until < 24;
//            System.out.println(until);
//            if (b) {
//                flag = false;
//            }
//        }
//        System.out.println(flag);

        System.out.println(DateUtil.date().toString("yyyy年MM月dd日"));
        System.out.println(DateUtil.date().toString("yyyy年MM月dd日"));
        System.out.println(DateUtil.yesterday().toString());
    }

    public static String getStringParameter(HttpServletRequest request, String attr, String defaultValue) {
        String str = request.getParameter(attr);
        return (str == null || str.equals("")) ? defaultValue : str.trim();
    }

    public static LocalDate getNexMonDate(LocalDate now, Integer repayDay, Integer x, String repayDayType) {
        int dayOfMonth = now.getDayOfMonth();
        //计算下一个还款日
        LocalDate nexMonDate = null;
        //对日还款
        if ("FORDAY".equals(repayDayType)) {
            if (dayOfMonth > 25) {
                //还款日-固定为25号
                nexMonDate = nexDate(now, now.getMonthValue() + 1, 25);
            } else {
                nexMonDate = now.plusMonths(1);
            }
        } else {
            //取当前时间的“年”，“月”，取已有还款日的“日”
            //x为：当前日期和已有还款日之间的天数
            LocalDate nex = nexDate(now, repayDay, now.getMonthValue() + 1);
            LocalDate nex2 = nexDate(now, repayDay, now.getMonthValue() + 2);
            //如果还款日大于25且非首次借款（已有还款日）
            if (dayOfMonth > 25 && ChronoUnit.DAYS.between(now, nex) < x) {
                //放款日距离账日小于15天，该借款订单首期还款顺延到下一个还款日，
                nexMonDate = nex2;
            } else {
                //放款日距离账日大于15天，则用已有还款日
                nexMonDate = nex;
            }
        }
        return nexMonDate;
    }

    public static void redisRedLock(LocalDate now, Integer repayDay, Integer x, String repayDayType) {
//        String lockKey = "boxKey" + ":" + req.getProductCode() + ":" + req.getBoxId();
//
//        RLock lock = redissonClient.getLock(lockKey);
//
//        try {
//            Boolean tryLock = lock.tryLock(20, 18, TimeUnit.SECONDS);
//            if (tryLock) {
//                //实现
//            }
//
//        } catch (RspCodeException e) {
//            AssertUtil.isTrue(false, e.getCode(), e.getMessage());
//        } catch (Exception e) {
//            log.error("{}", e.getMessage(), e);
//        } finally {
//            if (lock.isHeldByCurrentThread() && lock.isLocked()) {
//                lock.unlock();
//            }
//        }
    }

    private static String idsFormat(List<String> ids) {
        StringBuffer where = new StringBuffer();
        String join = String.join(",", ids);
        join = join.replace(",", "','");
        where = where.append(String.format("('%s')", join));
        return where.toString();
    }

    public static String getSerialNumber(String prefix) {
        Snowflake secondSnow = IdUtil.getSnowflake(1, 1);
        String secondId = secondSnow.nextIdStr();
        secondId = secondId.length() > 10 ? secondId.substring(0, 10) : secondId;
        return String.format("%s%s%s", prefix, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), secondId);
    }

    private static void getBetweenMinute() throws Exception {
//        Thread.sleep(5000);
        System.out.println("12121212");
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        System.out.println("12121212");
//        if (1==1){
//            throw new Exception("111");
//        }
//        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000 / 60;
    }

    /***
     * 计算下一个还款日
     * @param now           当前时间
     * @param oldRepayDate  已有还款日 首次传null
     * @param x             旧还款日和当前时间相差天数
     * @return
     */
    private static LocalDate getNexMonDate(LocalDate now, LocalDate oldRepayDate, int x) {
        int dayOfMonth = now.getDayOfMonth();
        //计算下一个还款日
        LocalDate nexMonDate = null;
        //是否已有还款日
        if (oldRepayDate != null) {
            //取当前时间的“年”，“月”，取已有还款日的“日”
            int dayOfMonth2 = oldRepayDate.getDayOfMonth();
            //当前日期和已有还款日之间的天数
            LocalDate nex = nexDate(now, dayOfMonth2, now.getMonthValue() + 1);
            LocalDate nex2 = nexDate(now, dayOfMonth2, now.getMonthValue() + 2);
            long between = ChronoUnit.DAYS.between(now, nex);
            //如果还款日大于25且非首次借款（已有还款日）
            if (dayOfMonth > 25 && between < x) {
                //放款日距离账日小于15天，该借款订单首期还款顺延到下一个还款日，
                nexMonDate = nex2;
            } else {
                //放款日距离账日大于15天，则用已有还款日
                nexMonDate = nex;
            }
        } else {
            if (dayOfMonth > 25) {
                //还款日-固定为25号
                nexMonDate = LocalDate.of(now.getYear(), now.getMonthValue() + 1, 25);
            } else {
                nexMonDate = now.plusMonths(1);
            }
        }
        return nexMonDate;
    }

//    private static LocalDate nexDate(LocalDate now, int monthPlus, int dayOfMonth) {
//        int year = now.getYear();
//        if (monthPlus > 12) {
//            return LocalDate.of(year + 1, monthPlus - 12, dayOfMonth);
//        }
//        return LocalDate.of(year, monthPlus - 12, dayOfMonth);
//    }

    private static LocalDate nexDate(LocalDate now, int dayOfMonth, int monthPlus) {
        int year = now.getYear();
        if (monthPlus > 12) {
            return LocalDate.of(year + 1, monthPlus - 12, dayOfMonth);
        }
        return LocalDate.of(year, monthPlus, dayOfMonth);
    }

    private static void aass() {
        Hashtable<Object, Object> hashtable = new Hashtable<>();
        System.out.println(hash("a"));
        System.out.println("================================");
        System.out.println(concurrntHash("a"));

//        HashMapTa<Object, Object> mapTa = new HashMapTa<>();
//        ConcurrentHashMap<Object, Object> mapTa1 = new ConcurrentHashMap<>();
//        mapTa.put("AaAaAaAaAa", "元素序号1");
//        mapTa.put("AaAaAaAaBB", "元素序号2");
//        mapTa.put("AaAaAaBBAa", "元素序号3");
//        mapTa.put("AaAaAaBBBB", "元素序号4");
//        mapTa.put("AaAaBBAaAa", "元素序号5");
//        mapTa.put("AaAaBBAaBB", "元素序号6");
//        mapTa.put("AaAaBBBBAa", "元素序号7");
//        mapTa.put("AaAaBBBBBB", "元素序号8");
//        mapTa.put("AaBBAaAaAa", "元素序号9");
//        mapTa.put("AaBBAaAaBB", "元素序号10");
//        mapTa.put("AaBBAaBBAa", "元素序号11");

//        HashMapTa<Object, Object> mapTa = new HashMapTa<>(8,0.75f);
//        mapTa.put("1", "元素序号1");
//        mapTa.put("2", "元素序号2");
//        mapTa.put("3", "元素序号3");
//        mapTa.put("4", "元素序号4");
//        mapTa.put("5", "元素序号5");
//        mapTa.put("6", "元素序号6");
//        mapTa.put("7", "元素序号7");
//        mapTa.put("8", "元素序号7");
//        mapTa.put("9", "元素序号7");
//        mapTa.put("10", "元素序号7");
//        mapTa.put("11", "元素序号7");
//        mapTa.put("12", "元素序号7");
//        long x1 = System.nanoTime();
//        System.out.println(x1-x);
    }

    private static void hash扩容正常() {
        HashMapTa<Object, Object> mapTa = new HashMapTa<>(8, 0.75F);
        mapTa.put("1", "元素序号1");
        mapTa.put("2", "元素序号2");
        mapTa.put("3", "元素序号3");
        mapTa.put("4", "元素序号4");
        mapTa.put("5", "元素序号5");
        mapTa.put("6", "元素序号6");
        mapTa.put("7", "元素序号7");
//        mapTa.put("8", "元素序号8");
//        mapTa.put("9", "元素序号9");
//        mapTa.put("10", "元素序号10");
//        mapTa.put("11", "元素序号11");

        //相同元素开始
//        mapTa.put("BBBBBBAaBB", "元素序号1");
//        mapTa.put("AaAaAaAaBB", "元素序号2");
//        mapTa.put("AaAaAaBBAa", "元素序号3");
//        mapTa.put("AaAaAaBBBB", "元素序号4");
//        mapTa.put("AaAaBBAaAa", "元素序号5");

        //再次put相同hash
//        mapTa.put("12", "元素序号12");
//        mapTa.put("13", "元素序号13");
//        mapTa.put("14", "元素序号14");
//        mapTa.put("15", "元素序号15");
//        mapTa.put("16", "元素序号16");
//        mapTa.put("17", "元素序号17");
//        mapTa.put("18", "元素序号18");
//        System.out.println(1 << 30);
    }

    private static void hash扩容() {
        HashMapTa<Object, Object> mapTa = new HashMapTa<>();
        mapTa.put("BBBBBBAaBB", "元素序号1");
        mapTa.put("AaAaAaAaBB", "元素序号2");
        mapTa.put("AaAaAaBBAa", "元素序号3");
        mapTa.put("AaAaAaBBBB", "元素序号4");
        mapTa.put("AaAaBBAaAa", "元素序号5");
        mapTa.put("AaAaBBAaBB", "元素序号6");
        mapTa.put("AaAaBBBBAa", "元素序号7");
        mapTa.put("AaAaBBBBBB", "元素序号8");
        mapTa.put("AaBBAaAaAa", "元素序号9");
        mapTa.put("AaBBAaAaBB", "元素序号10");
        mapTa.put("AaBBAaBBAa", "元素序号11");

        //相同元素开始
//        mapTa.put("AaAaBBBBBB", "a000");
//        mapTa.put("AaBBAaAaAa", "a000");
//        mapTa.put("AaBBAaAaBB", "a000");
//        mapTa.put("AaBBAaBBAa", "a000");

        //再次put相同hash
        mapTa.put("BBAaBBBBAa", "元素序号12");
        mapTa.put("BBAaBBBBBB", "元素序号13");
        mapTa.put("BBBBAaAaAa", "元素序号14");
        mapTa.put("BBBBAaAaBB", "元素序号15");
        mapTa.put("BBBBAaBBAa", "元素序号16");
        mapTa.put("BBBBAaBBBB", "元素序号17");
        mapTa.put("BBBBBBAaAa", "元素序号18");

        mapTa.remove("BBBBBBAaAa");
    }

    private static void extracted() {
        //hash值51628
        System.out.println(hash("AaAaAaAaAa"));
        System.out.println(hash("AaAaAaAaBB"));
        System.out.println(hash("AaAaAaBBAa"));
        System.out.println(hash("AaAaAaBBBB"));
        System.out.println(hash("AaAaBBAaAa"));
        System.out.println(hash("AaAaBBAaBB"));
        System.out.println(hash("AaAaBBBBAa"));
        System.out.println(hash("AaAaBBBBBB"));
        System.out.println(hash("AaBBAaAaAa"));
        System.out.println(hash("AaBBAaAaBB"));
        System.out.println(hash("AaBBAaBBAa"));
    }

    /***
     * 构造方法使用 不传入则默认
     * 计算hashmap的长度
     * @param cap
     */
    private static void tableSizeFor(int cap) {
        //最终结果一定是2的n次方
        //如果传入的数是奇数n  那就是大于等于n的下一个2的n次方 就是最终容量长度
        //7->8 15->16 1->1 16->16
        int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
        int re = (n < 0) ? 1 : (n >= 1 << 30) ? 1 << 30 : n + 1;
        System.out.println(re);
    }

    void readyMapParam(HttpServletRequest request, Map<String, String> map) {
        Map<String, String> requestMap = new HashMap<>();
        Enumeration<?> parmas = request.getParameterNames();
        StringBuffer requestBuf = new StringBuffer();
        while (parmas.hasMoreElements()) {
            Object object = parmas.nextElement();
            String name = object.toString();
            String value = getStringParameter(request, name, "");
            requestBuf.append(name + "=" + value + "&");
            requestMap.put(name, value);
            map.put(name, value);
        }
    }

}